package com.example.artwindow.config;

import com.example.artwindow.handler.AccessDeniedHandler;
import com.example.artwindow.service.impl.UserServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

	@Bean
	public PasswordEncoder passwordEncoder(){
		return new BCryptPasswordEncoder();
	}

	@Resource
	private UserServiceImpl userService;

	@Resource
	private AccessDeniedHandler accessDeniedHandler;

	@Bean
	public AuthenticationProvider authenticationProvider(){
		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
		provider.setPasswordEncoder(passwordEncoder());
		provider.setUserDetailsService(userService);
		return provider;
	}

	@Bean
	public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
		return configuration.getAuthenticationManager();
	}

	@Resource
	private JwtFilter jwtFilter;//jwt验证需要用到的过滤器


//	private static AuthenticationFailureHandler jsonAuthenticationFailureHandler() {
//		return (request, response, exception) -> {
//			response.setStatus(HttpStatus.OK.value());
//			response.setContentType("application/json;charset=UTF-8");
//			response.setCharacterEncoding(StandardCharsets.UTF_8.name());
//			response.getWriter().println(Result.error(HttpCodeEnum.ERR_NOT_LOGIN.getMsg(), HttpCodeEnum.ERR_NOT_LOGIN.getCode()));
//		};
//	}

	@Bean
	CorsConfigurationSource apiConfigurationSource() {
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.addAllowedOriginPattern("*");
		configuration.addAllowedMethod("*");
		configuration.addAllowedHeader("*");
		configuration.setAllowCredentials(true);
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}
	@Bean
	@Order(0)
	public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
		httpSecurity
				.formLogin(AbstractHttpConfigurer::disable)
				//取消默认登录页面的使用
				.logout(AbstractHttpConfigurer::disable)
				//取消默认登出页面的使用
				.authenticationProvider(authenticationProvider())
				//将自己配置的PasswordEncoder放入SecurityFilterChain中
				.csrf(AbstractHttpConfigurer::disable)
				//关闭csrf
				.cors((cors) -> cors
						.configurationSource(apiConfigurationSource()))
				//开启Cors中间件
				.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//禁用session，因为我们已经使用了JWT
				.httpBasic(AbstractHttpConfigurer::disable)
				//禁用httpBasic，因为我们传输数据用的是post，而且请求体是JSON
				.authorizeHttpRequests(
						request -> request
								.requestMatchers(HttpMethod.POST, "/admin/user/*").permitAll()
								.requestMatchers(HttpMethod.GET,"/test","/swagger-ui/*","/doc.html/**"
										,"/movie/*"
										,"/comment/**"
										,"/admin/**"
										,"/home/**"
										,"/recruit/**"
								).permitAll()
								.anyRequest()
								.authenticated())//开放接口
				.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
				.exceptionHandling(except->except.authenticationEntryPoint(accessDeniedHandler));
		//将用户授权时用到的JWT校验过滤器添加进SecurityFilterChain中，并放在UsernamePasswordAuthenticationFilter的前面
		return httpSecurity.build();
	}

}
